
#include <limits.h>
#include <gtest/gtest.h>
#include "hvrl/opengl/Camera.hpp"
#include "hvrl/opengl/IO.hpp"

TEST(OpenGLCameraTest, RotateRight) {
  Camera c;
  glm::vec3 front_init = c.getFront();
  glm::vec3 right_init = c.getRight();
  glm::vec3 up_init = c.getUp();
  c.rotate(0.0,90.0,0.0);
  glm::vec3 front = c.getFront();
  glm::vec3 right = c.getRight();
  glm::vec3 up = c.getUp();
  ASSERT_NEAR(right.x,right_init.x,0.000001f);
  ASSERT_NEAR(right.y,right_init.y,0.000001f);
  ASSERT_NEAR(right.z,right_init.z,0.000001f);
  ASSERT_FLOAT_EQ(glm::length(right),1.0);
  ASSERT_NEAR(up.x,front_init.x,0.000001f);
  ASSERT_NEAR(up.y,front_init.y,0.000001f);
  ASSERT_NEAR(up.z,front_init.z,0.000001f);
  ASSERT_FLOAT_EQ(glm::length(up),1.0);
  ASSERT_NEAR(front.x,-up_init.x,0.000001f);
  ASSERT_NEAR(front.y,-up_init.y,0.000001f);
  ASSERT_NEAR(front.z,-up_init.z,0.000001f);
  ASSERT_FLOAT_EQ(glm::length(front),1.0);
}

TEST(OpenGLCameraTest, RotateUp) {
  Camera c;
  glm::vec3 front_init = c.getFront();
  glm::vec3 right_init = c.getRight();
  glm::vec3 up_init = c.getUp();
  c.rotate(0.0,0.0,90.0);
  glm::vec3 front = c.getFront();
  glm::vec3 right = c.getRight();
  glm::vec3 up = c.getUp();
  ASSERT_NEAR(right.x,-front_init.x,0.000001f);
  ASSERT_NEAR(right.y,-front_init.y,0.000001f);
  ASSERT_NEAR(right.z,-front_init.z,0.000001f);
  ASSERT_FLOAT_EQ(glm::length(right),1.0);
  ASSERT_NEAR(up.x,up_init.x,0.000001f);
  ASSERT_NEAR(up.y,up_init.y,0.000001f);
  ASSERT_NEAR(up.z,up_init.z,0.000001f);
  ASSERT_FLOAT_EQ(glm::length(up),1.0);
  ASSERT_NEAR(front.x,right_init.x,0.000001f);
  ASSERT_NEAR(front.y,right_init.y,0.000001f);
  ASSERT_NEAR(front.z,right_init.z,0.000001f);
  ASSERT_FLOAT_EQ(glm::length(front),1.0);
}

TEST(OpenGLCameraTest, RotateFront) {
  Camera c;
  glm::vec3 front_init = c.getFront();
  glm::vec3 right_init = c.getRight();
  glm::vec3 up_init = c.getUp();
  c.rotate(90.0,0.0,0.0);
  glm::vec3 front = c.getFront();
  glm::vec3 right = c.getRight();
  glm::vec3 up = c.getUp();
  ASSERT_NEAR(right.x,up_init.x,0.000001f);
  ASSERT_NEAR(right.y,up_init.y,0.000001f);
  ASSERT_NEAR(right.z,up_init.z,0.000001f);
  ASSERT_FLOAT_EQ(glm::length(right),1.0);
  ASSERT_NEAR(up.x,-right_init.x,0.000001f);
  ASSERT_NEAR(up.y,-right_init.y,0.000001f);
  ASSERT_NEAR(up.z,-right_init.z,0.000001f);
  ASSERT_FLOAT_EQ(glm::length(up),1.0);
  ASSERT_NEAR(front.x,front_init.x,0.000001f);
  ASSERT_NEAR(front.y,front_init.y,0.000001f);
  ASSERT_NEAR(front.z,front_init.z,0.000001f);
  ASSERT_FLOAT_EQ(glm::length(front),1.0);
}

TEST(OpenGLCameraTest, Position) {
  Camera c;
  glm::vec3 new_position(10.04f,-10.05f,30.00001f);
  c.setPosition(new_position);
  ASSERT_TRUE(new_position == c.getPosition());
}

TEST(IO,matrixToString16){

    float m[16] = {1.0f,0.0f,-3.f,2.2365f,
                    0.0,0.0,0.0,0.0,
                    39.0,12634.2,6156,4.0,
                    0.05,.0,4145,4512};

    std::string s0 = "1 0 -3 2.2365 \n0 0 0 0 \n39 12634.2 6156 4 \n0.05 0 4145 4512 \n";
    std::string s1 = hvrl::matrixToString(m);
    ASSERT_TRUE(s0==s1);
}

TEST(IO,matrixToString5) {
    float m[5] = {1.0f,0.0f,-3.f,2.2365f,0.0};
    std::string s0 = "1 0 -3 2.2365 0 \n";
    std::string s1 = hvrl::matrixToString(m);
    ASSERT_TRUE(s0==s1);
}


